#pragma once
#include <iostream>
#include <memory>

#include "Socket.hpp"
#include "Connection.hpp"
#include "HandleConnection.hpp"

class Listener
{
public:
    Listener(uint16_t port, HandleConnection& hc)
        :_port(port)
        ,_sock(std::make_unique<sock::TcpSocket>("0.0.0.0", port))
        ,_hc(hc)
    {
        _sock->CreateSocket();
        _sock->BindSocket();
        _sock->Listen();
    }

    

    void Accept(Connection* conn)
    {
        while(true)
        {
            sockaddr_in client_addr;
            socklen_t len = sizeof(client_addr);
            int errcode = 0;
            int fd = _sock->Accept(&client_addr, &len, &errcode);
            LOG(INFO, "get a new link, fd = %d, errno = %d\n", fd, errcode);
            if(fd >= 0)
            {
                // 获取新链接
                conn->_R->AddConnection(fd, EPOLLIN | EPOLLET, 
                std::bind(&HandleConnection::HandleRecv, &_hc, std::placeholders::_1), 
                std::bind(&HandleConnection::HandleSend, &_hc, std::placeholders::_1), 
                std::bind(&HandleConnection::HandleExcept, &_hc, std::placeholders::_1));
            }
            else
            {
                if(errcode == EWOULDBLOCK || errcode == EAGAIN)
                {
                    // 链接获取完毕
                    LOG(INFO, "accept all link...\n");
                    break;
                }
                else if(errcode == EINTR)
                {
                    LOG(INFO, "accepter interupt by signal...\n");
                }
                else
                {
                    LOG(ERROR, "accept error...\n");
                    break;
                }
            }

        }
    }

    int GetListenSockfd()
    {
        return _sock->GetSockfd();
    }

    ~Listener()
    {
        _sock->Close();
    }
private:
    uint16_t _port;
    std::unique_ptr<sock::TcpSocket> _sock;
    HandleConnection& _hc;
};